Skip to content

VAP15-53 docs: document webhook credential withholding - #1221

Merged
jeffrey-hoekman-vapi merged 4 commits into
mainfrom
jeffhoekman/vap15-53-webhook-credentials-withheld-caller-supplied-server-url
Sep 17, 2026
Merged

jeffrey-hoekman-vapi merged 4 commits into
mainfrom
jeffhoekman/vap15-53-webhook-credentials-withheld-caller-supplied-server-url

Conversation

@jeffrey-hoekman-vapi

@jeffrey-hoekman-vapi jeffrey-hoekman-vapi commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Linear ticket

VAP15-53 — https://linear.app/vapi/issue/VAP15-53

Value

V.A.L.U.E. tier: micro — docs-only, one file, no blast-radius path.

VAPSEC-564/619/623 changed a documented contract: when a server URL arrives in the request itself — a transient assistant, or assistantOverrides — Vapi no longer attaches the org's webhook credential, and credential fields in the payload arrive as "[REDACTED]". The docs still promised the old behavior, so a customer hitting this sees an unauthenticated webhook and no explanation — indistinguishable from a broken listener.

Affects: orgs on the caller-supplied server-URL path (97 in the VAPSEC-564 cohort), plus every org created after the VAPSEC-689 cutoff. Secondarily CS and FDE, who field the "my webhook stopped authenticating" ticket.

What changed

All in fern/server-url/server-authentication.mdx:

  1. A Quick start warning. The "Test your webhook" step promised "Vapi will now authenticate requests to your webhook using the configured credential" unconditionally. The condition now travels with the promise, where a reader meets it, rather than 300 lines later.
  2. A ### When credentials are not attached section — which paths are caller-authored, the explicit contrast that saved assistants / phone numbers / tools keep their credentials, and the [REDACTED] payload note.
  3. #### Confirming a withheld send in your logs — what support actually needs: the literal log string, the suppressed high-volume message types, and the trap that a missing log entry does not mean credentials were sent.
  4. A rollout qualifier (see blocker below).

Why the rollout qualifier is here

Without it the page states the withholding unconditionally, while pre-cutoff orgs are still gated by ENABLE_WEBHOOK_CREDENTIAL_BINDING. An unenrolled org could read "no X-Vapi-Secret header" and conclude its org secret is not reaching a third-party URL — when it still is. That is an inaccuracy in the unsafe direction, so the qualifier is not optional polish.

It deliberately does not tell a pre-cutoff org when their turn comes. The ramp is a hand-maintained override list with a limited number of slots, mostly already allocated; an invitation to request enrollment would be a promise we cannot service.

Cutoff date

2026-09-23 (UTC), matching WEBHOOK_CREDENTIAL_BINDING_CUTOFF in https://github.com/VapiAI/vapi/pull/19995. The ENFORCEMENT_DATE_TBD placeholder and its TODO are gone; nothing blocks merge.

VAPSEC-689 deploys Monday 2026-09-21. 2026-09-23T00:00:00.000Z is Tuesday 5pm Pacific, roughly thirty hours after a Monday-midday deploy, and it survives a slip into Tuesday morning. A cutoff written as 2026-09-22 would have resolved to Monday 5pm Pacific — the same day as the deploy and possibly before it, tripping the cutoff-ahead-of-BUILD_DATE invariant that PR #19995 machine-checks.

The page says (UTC) because the boundary is an instant, not a calendar day: an org created Tuesday 5pm Pacific is created on 2026-09-23 UTC and is enforced, while its owner believes they signed up on the 22nd.

Merge gate

  • VAPSEC-564/619/623 have deployed. The original gate is satisfied.
  • Merge before 2026-09-23T00:00:00.000Z, not merely "around the same time as VAPSEC-689". Enforcement for new orgs begins at the cutoff, which is by construction later than that PR's deploy. From that moment every brand-new org gets this behavior during onboarding — and unlike the migration cohort, a brand-new org cannot be warned in advance and has no CS relationship yet. This page is the only explanation it will ever get. Landing early is harmless: it describes behavior already true for the enrolled cohort, now correctly qualified. If the cutoff date moves, this deadline moves with it.
  • Accurate for both populations: the ENABLE_WEBHOOK_CREDENTIAL_BINDING cohort, and — from the cutoff onward — unconditionally every newly created org.

Follow-on obligations

Trigger Action
VAPSEC-689 cutoff date moves This page hardcodes 2026-09-23 (UTC) and Fern cannot interpolate it, so a move needs a companion docs PR. Recorded on VAPSEC-689.
VAPSEC-654 deletes the flag, ramp at 100 The rollout qualifier becomes false and must be removed. Recorded on VAPSEC-654.
VAPSEC-627 ships Subsystem server URLs (tools, KB, custom voice, handoff/transfer destinations, endpointing) — VAP15-54, stacked on this branch, still provisional.

Evidence

Check Result
fern check 0 errors, 12 warnings (pre-existing OpenAPI discriminator warnings, untouched by this PR)
Prose verified against serverUrlFunctions.ts, serverMessageUtil.ts, serverUrlFunctions.secretBinding.spec.ts, sessionFunctions.secretBinding.spec.ts

Out of scope

The message-options override paths (handoff-destination-request, tools, KB, custom voice, endpointing) belong to VAPSEC-627 and are tracked in VAP15-54. Documenting them here would publish behavior that is not yet true and would disclose an open finding.

Refs VAPSEC-564, VAPSEC-619, VAPSEC-623, VAPSEC-689.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

Comment thread fern/server-url/server-authentication.mdx Outdated
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

VAPSEC-564/619/623 changed a documented contract: when a server URL
arrives in the API request itself - a transient assistant, or
assistantOverrides - Vapi no longer attaches the org's webhook
credential, and credential fields in the payload arrive as [REDACTED].
The page still promised the old behavior, so a customer hitting this
sees an unauthenticated webhook and no explanation, indistinguishable
from a broken listener.

Adds three things to fern/server-url/server-authentication.mdx:

- A Quick start warning, so the "Vapi will now authenticate requests"
  promise carries its condition where a reader meets it rather than 300
  lines later.
- A "When credentials are not attached" section: which paths are
  caller-authored, the contrast that saved assistants, phone numbers and
  tools keep their credentials, and the [REDACTED] payload note.
- "Confirming a withheld send in your logs", carrying what support
  needs: the literal log string, the suppressed high-volume message
  types, and the trap that a missing entry does not mean credentials
  were sent.

The rollout qualifier is not optional polish. Without it the page states
the withholding unconditionally while pre-cutoff orgs are still gated by
ENABLE_WEBHOOK_CREDENTIAL_BINDING, so an unenrolled org could read "no
X-Vapi-Secret header" and conclude its secret is not reaching a
third-party URL when it still is - an inaccuracy in the unsafe
direction. It deliberately does not invite enrollment requests; the ramp
is a hand-maintained list with limited slots, mostly allocated.

ENFORCEMENT_DATE_TBD is a literal placeholder and a merge blocker. The
VAPSEC-689 cutoff is still being settled with the CISO, infosec and the
EM. A non-rendering MDX comment marks the spot.

Scoped to the webhook server URL. The message-options override paths
(tools, KB, custom voice, handoff and transfer destinations,
endpointing) are VAPSEC-627 and are documented separately in VAP15-54.

fern check: 0 errors, 12 pre-existing discriminator warnings.

Refs VAP15-53, VAPSEC-564, VAPSEC-619, VAPSEC-623, VAPSEC-689

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jeffrey-hoekman-vapi
jeffrey-hoekman-vapi force-pushed the jeffhoekman/vap15-53-webhook-credentials-withheld-caller-supplied-server-url branch from 056e643 to a2c1858 Compare September 16, 2026 18:01
@jeffrey-hoekman-vapi jeffrey-hoekman-vapi changed the title VAP15-53 docs(server-url): document credential withholding on caller-supplied server urls VAP15-53 docs: document webhook credential withholding Sep 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@jeffrey-hoekman-vapi
jeffrey-hoekman-vapi marked this pull request as ready for review September 16, 2026 18:08
@lightsage-app

lightsage-app Bot commented Sep 16, 2026

Copy link
Copy Markdown

Lightsage docs evals

Result: passed
Staging docs: https://vapi-preview-01a0abad-3dae-732a-821f-d99b381db8d1.docs.buildwithfern.com
Commit: a95979a

Average score: 100/100
Passed: 3/3

Eval ID Status Score Model Tools Docs 404
08e24c18-82a0-45de-abdc-d237bd12bc0f Pass 100 claude-code/global.anthropic.claude... 12 0
08e24c18-82a0-45de-abdc-d237bd12bc0f Pass 100 codex/gpt-5.4 19 0
08e24c18-82a0-45de-abdc-d237bd12bc0f Pass 100 cursor/auto 13 0

@stephenvapiai stephenvapiai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Editorial pass on the 44 added lines, scoped to changed passages. All ten are suggestions you can apply or wave off — nothing here is a correctness claim about the withholding behavior itself, which I took as given.

Themes: active voice with Vapi as the actor, a spaced hyphen used as a dash in four places (§9 allows em dashes sparingly and en dashes in ranges, but not -), parameter vs field at line 407, and callout density — the page goes from one <Warning> to five, so I've suggested the rollout qualifier become a <Note>.

Deliberately untouched: the ENFORCEMENT_DATE_TBD placeholder and its TODO, the log string and every technical literal, and the two <Warning>s that flag real consequences.

Heading case is worth noting but not fixing here — your two new headings are sentence case, which is what §9 asks for; the rest of the page is Title Case from before.

Comment thread fern/server-url/server-authentication.mdx Outdated
Comment thread fern/server-url/server-authentication.mdx Outdated
Comment thread fern/server-url/server-authentication.mdx Outdated
Comment thread fern/server-url/server-authentication.mdx Outdated
Comment thread fern/server-url/server-authentication.mdx Outdated
Comment thread fern/server-url/server-authentication.mdx Outdated
Comment thread fern/server-url/server-authentication.mdx Outdated
Comment thread fern/server-url/server-authentication.mdx Outdated
Comment thread fern/server-url/server-authentication.mdx Outdated
Comment thread fern/server-url/server-authentication.mdx Outdated
Replaces the ENFORCEMENT_DATE_TBD placeholder and drops the TODO that
guarded it. Unblocks merge.

VAPSEC-689 deploys on Monday 2026-09-21. The date is stated in UTC
because 2026-09-23T00:00:00Z is Tuesday 5pm Pacific: a cutoff written
as "2026-09-22" would have landed Monday 5pm Pacific, the same day as
the deploy and possibly before it, which trips the cutoff-ahead-of-
BUILD_DATE invariant that PR #19995 machine-checks. Wednesday UTC
leaves roughly thirty hours of margin and survives a Monday slip.

The (UTC) marker is there because the boundary is an instant, not a
calendar day. An org created Tuesday 5pm Pacific is created on
2026-09-23 UTC and is enforced, while its owner believes they signed
up on the 22nd.

This date must stay in sync with WEBHOOK_CREDENTIAL_BINDING_CUTOFF.
Fern cannot interpolate it, so a cutoff change needs a companion docs
PR. Recorded on VAPSEC-689.

Refs VAP15-53, VAPSEC-689

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Voice and terminology pass. Vapi becomes the actor throughout, spaced
hyphens become periods or colons, the log fence is tagged text, and the
suppressed-entry warning leads with what the reader actually has in
front of them. "Server Configuration" now matches the dashboard label
used in Quick start, and server.headers is called a field rather than a
parameter.

Two of the suggestions are applied with changes.

The redaction sentence keeps its explicit scope. Steve's version opened
"Vapi also strips credential fields", which drops the condition; the
condition is the whole point, since payloads on org-configured URLs are
not stripped, and a reader arriving by deep link has no surrounding
context to infer it from. Takes the active voice without the cut.

The rollout callout stays a Warning rather than becoming a Note. The
concern behind the suggestion is real - four stacked Warnings train
readers to skip them - but for an org that the phased rollout has not
reached, this paragraph is the harm notice: the org credential is still
going out to caller-supplied URLs today. Its terminology cleanup is
applied, so one term covers what was four.

Refs VAP15-53

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Takes the last of Steve's suggestions. Four stacked Warnings in forty
lines train readers to skip them, and this paragraph is the weakest
candidate to keep as a Warning: its text is unchanged either way, and
the whole callout is deleted under VAPSEC-654 once the flag is gone and
the rollout no longer exists to qualify.

Refs VAP15-53, VAPSEC-654

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

@jeffrey-hoekman-vapi
jeffrey-hoekman-vapi merged commit 9dbac05 into main Sep 17, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants